package net.hn.hnms.biz.equipment.company.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import net.hn.hnms.biz.equipment.company.domain.dto.CompanyProductionStatementDto;
import net.hn.hnms.biz.equipment.company.service.CompanyServer;
import net.hn.hnms.biz.equipment.domain.dto.EquipmentStartDayDto;
import net.hn.hnms.biz.equipment.domain.dto.ProductionStatementDto;
import net.hn.hnms.biz.equipment.domain.vo.ChartOperationRateVO;
import net.hn.hnms.biz.equipment.domain.vo.ProductionStatementVo;
import net.hn.hnms.biz.equipment.mapper.EquipmentStartDayMapper;
import net.hn.hnms.biz.equipment.mapper.EquipmentStartDetailsDayMapper;
import net.hn.hnms.biz.equipment.service.EquipmentService;
import net.hn.hnms.sys.common.core.constant.Constants;
import net.hn.hnms.sys.common.core.exception.HuaNengException;
import net.hn.hnms.sys.common.core.utils.StringUtils;
import net.hn.hnms.sys.common.redis.domain.SysOrganization;
import net.hn.hnms.sys.common.redis.domain.SysOrganizationVo;
import net.hn.hnms.sys.common.redis.utils.RedisUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

@Service
public class CompanyServerImpl implements CompanyServer {
    /**
     * 重大设备开机起始Mapper
     */
    @Resource
    private EquipmentStartDayMapper equipmentStartDayMapper;
    /**
     * 重大设备开机起始区间Mapper
     */
    @Resource
    private EquipmentStartDetailsDayMapper equipmentStartDetailsDayMapper;

    /**
     * 重大设备服务
     */
    @Resource
    private EquipmentService equipmentService;
    /**
     * 生产看板-本月开机率台账
     *
     * @return
     */
    @Override
    //设备开机率计算公式： （设备实际工作时间/总可工作时间）*100%
    public Map operationRate(String companyCode, String mineCode, Date month) {
        //判断传参日期是否为空，为空则默认使用当前时间
        //获取当月的开始日期
        DateTime startTime = null;
        //获取当月的结束日期
        DateTime endTime = null;
        if (month == null) {
            //获取当月的开始日期
            startTime = DateUtil.beginOfMonth(new Date());
            //获取当月的结束日期
            endTime = DateUtil.endOfMonth(new Date());

        } else {
            startTime = DateUtil.beginOfMonth(month);
            //获取当月的结束日期
            endTime = DateUtil.endOfMonth(month);
        }
        //获取当月的间隔，单位天数
        Long offSet = DateUtil.betweenDay(startTime, endTime, true);

//        List<EquipmentStartDayDto> equipmentStartDayDtoList=equipmentStartDetailsDayMapper.operationRate(DateUtil.formatDate(startTime), Math.toIntExact(offSet),companyCode,mineCode);
        List<EquipmentStartDayDto> equipmentStartDayDtoList = equipmentStartDetailsDayMapper.operationRateByDataFlag(DateUtil.formatDateTime(startTime), DateUtil.formatDateTime(endTime), companyCode, mineCode);
        //以时间进行分组 并排序
        Map<Date, List<EquipmentStartDayDto>> dateListMap = equipmentStartDayDtoList.stream().collect(Collectors.groupingBy(EquipmentStartDayDto::getDateTime, LinkedHashMap::new,Collectors.toList()));
        //返回数据vo
        ChartOperationRateVO chartOperationRateVO = new ChartOperationRateVO();
        //x轴方向
        List<String> listX = new ArrayList<>();
        //割煤机开机率  0
        List<BigDecimal> coalCutterValue = new ArrayList<>();
        //掘进机开机率 1
        List<BigDecimal> tunnelBorerValue = new ArrayList<>();
        //煤流皮带运输开机率 2
        List<BigDecimal> beltConveyorValue = new ArrayList<>();
        //斜井提升开机率  3
        List<BigDecimal> inclineShaftValue = new ArrayList<>();
        //主通风机开机率 4
        List<BigDecimal> ventilatorValue = new ArrayList<>();
        //压风机开机率  5
        List<BigDecimal> compressorValue = new ArrayList<>();
        //主排水泵开机率  6
        List<BigDecimal> pumpValue = new ArrayList<>();
        //制氮开机率  8
        List<BigDecimal> nitrogenValue = new ArrayList<>();
        //封装返回结果
        dateListMap.forEach((k,v)->{
            //x轴返回时间  一个循环代表一天
            listX.add(new SimpleDateFormat("yyyy-MM-dd").format(k));
            //当天内的所有系统，

            //根据系统进行分组。遍历每个系统的所有设备
            //判断系统是否为空，为空则将系统编码置为-1
            Map<Integer, List<EquipmentStartDayDto>> integerListMap = v.stream().collect(Collectors.groupingBy(x -> Optional.ofNullable(x.getEquipmentFlag()).orElse(-1)));


            integerListMap.forEach((a, b) -> {
                //判断返回equipmentFlag重大设备标识，0代表采煤机，1代表掘进机， 2代表皮带运输，3代表斜井提升，4代表主通风机 5代表压风机，6代表主排水
                if (0 == a) {
                    //采煤机割煤机
                    //遍历采煤机的所有设备
                    //所有的设备开机率相加=总开机率
                    BigDecimal coalCutterBigDecimal = new BigDecimal(0);
                    for (EquipmentStartDayDto equipmentStartDayDto : b) {
                        coalCutterBigDecimal=coalCutterBigDecimal.add(new BigDecimal(equipmentStartDayDto.getRate()));
                    }
                    //封装采煤机
                    //保留三位小数，多余的删除
                    coalCutterValue.add(coalCutterBigDecimal.setScale(3,BigDecimal.ROUND_DOWN));
                } else if (1 == a) {
                    //掘进机
                    BigDecimal tunnelBorerBigDecimal = new BigDecimal(0);
                    for (EquipmentStartDayDto equipmentStartDayDto : b) {
                        tunnelBorerBigDecimal=tunnelBorerBigDecimal.add(new BigDecimal(equipmentStartDayDto.getRate()));
                    }
                    //封装掘进机
                    tunnelBorerValue.add(tunnelBorerBigDecimal.setScale(3,BigDecimal.ROUND_DOWN));
                } else if (2 == a) {
                    //煤流皮带
                    BigDecimal beltConveyorBigDecimal = new BigDecimal(0);
                    for (EquipmentStartDayDto equipmentStartDayDto : b) {
                        beltConveyorBigDecimal=beltConveyorBigDecimal.add(new BigDecimal(equipmentStartDayDto.getRate()));
                    }
                    //判断开机率是否大于一百
                    BigDecimal hundred = new BigDecimal(100);
                    if (beltConveyorBigDecimal.compareTo(hundred) > 0) {
//                        System.out.println("beltConveyorBigDecimal 大于一百");
                        //证明数据库存在数据异常 可能有重复时间数据
                        //进行数据筛选 获取开机率
                        BigDecimal sunRate = getSunRate(b);
                        beltConveyorValue.add(sunRate.setScale(3,BigDecimal.ROUND_DOWN));
                    } else {
                        //不大于一百的逻辑
                        //封装煤流皮带
                        beltConveyorValue.add(beltConveyorBigDecimal.setScale(3,BigDecimal.ROUND_DOWN));
                    }


                } else if (3 == a) {
                    //斜井提升
                    BigDecimal inclineShaftValueBigDecimal = new BigDecimal(0);
                    for (EquipmentStartDayDto equipmentStartDayDto : b) {
                        inclineShaftValueBigDecimal=inclineShaftValueBigDecimal.add(new BigDecimal(equipmentStartDayDto.getRate()));
                    }
                    //封装斜井提升
                    inclineShaftValue.add(inclineShaftValueBigDecimal.setScale(3,BigDecimal.ROUND_DOWN));

                } else if (4 == a) {
                    //主通风机
                    BigDecimal ventilatorValueBigDecimal = new BigDecimal(0);
                    for (EquipmentStartDayDto equipmentStartDayDto : b) {
                        ventilatorValueBigDecimal=ventilatorValueBigDecimal.add(new BigDecimal(equipmentStartDayDto.getRate()));
                    }
                    //封装主通风机
                    ventilatorValue.add(ventilatorValueBigDecimal.setScale(3,BigDecimal.ROUND_DOWN));

                } else if (5 == a) {
                    //压风机
                    BigDecimal compressorValueBigDecimal = new BigDecimal(0);
                    for (EquipmentStartDayDto equipmentStartDayDto : b) {
                        compressorValueBigDecimal=compressorValueBigDecimal.add(new BigDecimal(equipmentStartDayDto.getRate()));
                    }
                    //封装压风机
                    compressorValue.add(compressorValueBigDecimal.setScale(3,BigDecimal.ROUND_DOWN));

                } else if (6 == a) {
                    //主排水
                    BigDecimal pumpValueBigDecimal = new BigDecimal(0);
                    for (EquipmentStartDayDto equipmentStartDayDto : b) {
                        pumpValueBigDecimal=pumpValueBigDecimal.add(new BigDecimal(equipmentStartDayDto.getRate()));
                    }
                    //封装主排水
                    pumpValue.add(pumpValueBigDecimal.setScale(3,BigDecimal.ROUND_DOWN));

                }else if (8 == a) {
                    //制氮
                    BigDecimal nitrogenValueBigDecimal = new BigDecimal(0);
                    for (EquipmentStartDayDto equipmentStartDayDto : b) {
                        nitrogenValueBigDecimal=nitrogenValueBigDecimal.add(new BigDecimal(equipmentStartDayDto.getRate()));
                    }
                    //封装主排水
                    nitrogenValue.add(nitrogenValueBigDecimal.setScale(3,BigDecimal.ROUND_DOWN));

                }


            });
//            //判断采煤机数值及系统,若没有系统，则开机率置为零
//            if (coalCutterValue.size() != listX.size()) {coalCutterValue.add(new BigDecimal(0.000));}
//            //掘进机开机率
//            if (tunnelBorerValue.size() != listX.size()) {tunnelBorerValue.add(new BigDecimal(0.000));}
//            //煤流皮带运输开机率
//            if (beltConveyorValue.size() != listX.size()) {beltConveyorValue.add(new BigDecimal(0.000));}
//            //斜井提升开机率
//            if (inclineShaftValue.size() != listX.size()) {inclineShaftValue.add(new BigDecimal(0.000));}
//            //主通风机开机率
//            if (ventilatorValue.size() != listX.size()) {ventilatorValue.add(new BigDecimal(0.000));}
//            //压风机开机率
//            if (compressorValue.size() != listX.size()) {compressorValue.add(new BigDecimal(0.000));}
//            //主排水泵开机率
//            if (pumpValue.size() != listX.size()) {pumpValue.add(new BigDecimal(0.000));}
//            //制氮开机率
//            if (nitrogenValue.size() != listX.size()) {nitrogenValue.add(new BigDecimal(0.000));}
            //判断采煤机数值及系统,若没有系统，则开机率置为null
            if (coalCutterValue.size() != listX.size()) {coalCutterValue.add(null);}
            //掘进机开机率
            if (tunnelBorerValue.size() != listX.size()) {tunnelBorerValue.add(null);}
            //煤流皮带运输开机率
            if (beltConveyorValue.size() != listX.size()) {beltConveyorValue.add(null);}
            //斜井提升开机率
            if (inclineShaftValue.size() != listX.size()) {inclineShaftValue.add(null);}
            //主通风机开机率
            if (ventilatorValue.size() != listX.size()) {ventilatorValue.add(null);}
            //压风机开机率
            if (compressorValue.size() != listX.size()) {compressorValue.add(null);}
            //主排水泵开机率
            if (pumpValue.size() != listX.size()) {pumpValue.add(null);}
            //制氮开机率
            if (nitrogenValue.size() != listX.size()) {nitrogenValue.add(null);}



        });
        //返回格式封装
        //x时间
        chartOperationRateVO.setXName(listX);
        //采煤机
        chartOperationRateVO.setCoalCutterValue(coalCutterValue);
        //掘进机开机率
        chartOperationRateVO.setTunnelBorerValue(tunnelBorerValue);
        //煤流皮带运输开机率
        chartOperationRateVO.setBeltConveyorValue(beltConveyorValue);
        //斜井提升开机率
        chartOperationRateVO.setInclineShaftValue(inclineShaftValue);
        //主通风机开机率
        chartOperationRateVO.setVentilatorValue(ventilatorValue);
        //压风机开机率
        chartOperationRateVO.setCompressorValue(compressorValue);
        //主排水泵开机率
        chartOperationRateVO.setPumpValue(pumpValue);
        //制氮开机率
        chartOperationRateVO.setNitrogenValue(nitrogenValue);
        Map<String,Object> map = new HashMap();

        if ("620824009734".equals(mineCode)) {
            //砚北
            //x方向值
            map.put("xName", chartOperationRateVO.getXName());
            //割煤机开机率
            map.put("coalCutterValue", chartOperationRateVO.getCoalCutterValue());
            //掘进机开机率
            map.put("tunnelBorerValue", chartOperationRateVO.getTunnelBorerValue());
            //煤流皮带运输开机率
            map.put("beltConveyorValue", chartOperationRateVO.getBeltConveyorValue());
            //斜井提升开机率
            map.put("inclineShaftValue", chartOperationRateVO.getInclineShaftValue());
            //主通风机开机率
            map.put("ventilatorValue", chartOperationRateVO.getVentilatorValue());
            //压风机开机率
            map.put("compressorValue", chartOperationRateVO.getCompressorValue());
            //主排水泵开机率
            map.put("pumpValue", chartOperationRateVO.getPumpValue());

        } else if ("150621011038".equals(mineCode)) {
            //高头窑
            //x方向值
            map.put("xName", chartOperationRateVO.getXName());
            //割煤机开机率
            map.put("coalCutterValue", chartOperationRateVO.getCoalCutterValue());
            //掘进机开机率
            map.put("tunnelBorerValue", chartOperationRateVO.getTunnelBorerValue());
            //煤流皮带运输开机率
            map.put("beltConveyorValue", chartOperationRateVO.getBeltConveyorValue());
            //斜井提升开机率
            map.put("inclineShaftValue", chartOperationRateVO.getInclineShaftValue());
            //主通风机开机率
            map.put("ventilatorValue", chartOperationRateVO.getVentilatorValue());
            //压风机开机率
            map.put("compressorValue", chartOperationRateVO.getCompressorValue());
            //主排水泵开机率
            map.put("pumpValue", chartOperationRateVO.getPumpValue());
            //制氮开机率
            map.put("nitrogenValue", chartOperationRateVO.getNitrogenValue());
        } else {
            //展示所有子系统
            //x方向值
            map.put("xName", chartOperationRateVO.getXName());
            //割煤机开机率
            map.put("coalCutterValue", chartOperationRateVO.getCoalCutterValue());
            //掘进机开机率
            map.put("tunnelBorerValue", chartOperationRateVO.getTunnelBorerValue());
            //煤流皮带运输开机率
            map.put("beltConveyorValue", chartOperationRateVO.getBeltConveyorValue());
            //斜井提升开机率
            map.put("inclineShaftValue", chartOperationRateVO.getInclineShaftValue());
            //主通风机开机率
            map.put("ventilatorValue", chartOperationRateVO.getVentilatorValue());
            //压风机开机率
            map.put("compressorValue", chartOperationRateVO.getCompressorValue());
            //主排水泵开机率
            map.put("pumpValue", chartOperationRateVO.getPumpValue());
            //制氮开机率
            map.put("nitrogenValue", chartOperationRateVO.getNitrogenValue());
        }
        return map;
    }

    /**
     * 获取总开机率
     * @param equipmentStartDayDtoList
     * @return
     */
    private BigDecimal getSunRate(List<EquipmentStartDayDto> equipmentStartDayDtoList) {
        BigDecimal sumTimeListBigDecimal = new BigDecimal(0);
        List<EquipmentStartDayDto> sumTimeList = getSumTimeList(equipmentStartDayDtoList);
        for (EquipmentStartDayDto equipmentStartDayDto : sumTimeList) {
            sumTimeListBigDecimal=sumTimeListBigDecimal.add(new BigDecimal(equipmentStartDayDto.getRate()));
        }
        return sumTimeListBigDecimal;
    }

    /**
     * 整理时间段 汇总并集时间数据
     * @param equipmentStartDayDtos
     * @return
     */
    private  List<EquipmentStartDayDto> getSumTimeList(List<EquipmentStartDayDto> equipmentStartDayDtos) {
        //根据开始时间进行排序
        List<EquipmentStartDayDto> sortedList = equipmentStartDayDtos.stream()
                .sorted((o1, o2) -> o1.getStartBTime().compareTo(o2.getStartBTime()))
                .collect(toList());

        //并集集合
        List<EquipmentStartDayDto> equipmentStartDayDtos11 = new ArrayList<>();

        //遍历集合 提取并集集合
        for (int i = 0; i < sortedList.size(); i++) {
            //获取结束时间
            Date endTIme = null;

            if (equipmentStartDayDtos11.isEmpty()) {
                //没有结束时间  代表刚一开始  将当前数据赋值到集合中
                equipmentStartDayDtos11.add(sortedList.get(i));
                continue;
            }
            EquipmentStartDayDto equipmentStartDayDto1 = equipmentStartDayDtos11.get(equipmentStartDayDtos11.size()-1);
            if (equipmentStartDayDto1 != null && equipmentStartDayDto1.getStartBTime() != null) {
                endTIme = equipmentStartDayDto1.getStartETime();
            }
            //判断当前结束时间是否大于开始时间
            if (endTIme.after(sortedList.get(i).getStartBTime())) {
                //代表当前时间段与下一组时间段存在交集
                //判断下一组结束时间是否大于 结束时间
                if (sortedList.get(i).getStartETime().after(endTIme)) {
                    //如果下一组结束时间 大于 结束时间
                    //意味着交集需要扩大
                    //更新数据 将下一组的结束时间 放在此结束时间
                    equipmentStartDayDto1.setStartETime(sortedList.get(i).getStartETime());
                } else {
                    //意味着交集不动 舍弃数据
                }

            } else {
                //结束时间 小于与开始时间  需要分段时间
                EquipmentStartDayDto equipmentStartDayDto = new EquipmentStartDayDto();
                BeanUtil.copyProperties(sortedList.get(i), equipmentStartDayDto);
                equipmentStartDayDtos11.add(equipmentStartDayDto);
            }
        }

        for (EquipmentStartDayDto equipmentStartDayDto : equipmentStartDayDtos11) {
            //求开机率
            long startTime = equipmentStartDayDto.getStartBTime().getTime();
            long endtime = equipmentStartDayDto.getStartETime().getTime();
            long diffMillis = endtime - startTime;
            //设备开机时间（分钟）
            long minutes = diffMillis / (60 * 1000);
            //求开机率  当前设备开机时间（分钟）除以一天的总时间（分钟1440）*100
            float rate = (float) minutes / 1440 * 100;
            float roundedRate = (float) (Math.round(rate * 100.0) / 100.0);
            equipmentStartDayDto.setRate(roundedRate);
        }
        return equipmentStartDayDtos11;
    }

    /**
     * 生产报表-根据生产设备类型获取生产报表
     * @param companyProductionStatementDto
     * @return
     */
    @Override
    public List<ProductionStatementVo> getCompanyProductionStatementBydeviceType(CompanyProductionStatementDto companyProductionStatementDto) {
        if (StringUtils.isEmpty(companyProductionStatementDto.getCompanyCode())) {
            throw new HuaNengException(Constants.FAIL, "公司编码不能为空");
        }
        if (StringUtils.isNotBlank(companyProductionStatementDto.getMineCode())) {
            //煤矿编码不为空
            //组装矿端生产报表查询条件
            ProductionStatementDto productionStatementDto = new ProductionStatementDto(
                    companyProductionStatementDto.getDeviceTypeCode(), companyProductionStatementDto.getStartDate(),
                    companyProductionStatementDto.getEndDate(), companyProductionStatementDto.getMineCode());
            //查询当前煤矿编码下的数据
            //获取矿端生产报表
            List<ProductionStatementVo> productionStatementBydeviceType = equipmentService.getProductionStatementBydeviceType(productionStatementDto);
            //获取煤矿信息
            SysOrganization sysOrganization = RedisUtils.getCacheObject(Constants.SYS_CODE_KEY + companyProductionStatementDto.getMineCode());
            if (sysOrganization == null) {
                throw new HuaNengException(Constants.FAIL, "无法获取sysOrganization");
            }
            return productionStatementBydeviceType;
        } else {
            List<ProductionStatementVo> productionStatementBydeviceTypeall = new ArrayList<>();
            //煤矿编码为空 查询所有的煤矿
            SysOrganizationVo sysOrganizationVoList = RedisUtils.getCacheObject(Constants.SYS_CODESUB_KEY + companyProductionStatementDto.getCompanyCode());
            if (sysOrganizationVoList == null) {
                throw new HuaNengException(Constants.FAIL, "无法获取SysOrganizationVo列表，请检查煤矿编码词典缓存");
            }
            //获取当前公司下所有煤矿列表
            for (SysOrganizationVo sysOrganizationVo : sysOrganizationVoList.getSubCodeList()) {
                //组装矿端生产报表查询条件
                ProductionStatementDto productionStatementDto = new ProductionStatementDto(
                        companyProductionStatementDto.getDeviceTypeCode(), companyProductionStatementDto.getStartDate(),
                        companyProductionStatementDto.getEndDate(), sysOrganizationVo.getOrgCode());
                //查询当前煤矿编码下的数据
                //获取矿端生产报表
                List<ProductionStatementVo> productionStatementBydeviceType = equipmentService.getProductionStatementBydeviceType(productionStatementDto);
                if (productionStatementBydeviceType.isEmpty()) {
                    //矿端生产报表为空
                    productionStatementBydeviceTypeall.add(
                            new ProductionStatementVo("---", "---", "---", "---", "---", "---", "---", "---", "---", "---", "---", "---", "---", "---", "---", "---", sysOrganizationVo.getOrgCode(), sysOrganizationVo.getOrgName()));
                } else {
                    for (ProductionStatementVo productionStatementVo : productionStatementBydeviceType) {
                        productionStatementBydeviceTypeall.add(productionStatementVo);
                    }
                }


            }
            return productionStatementBydeviceTypeall;
        }
    }
}
